import { initDevice } from "@/func/initDevice";
import {
  acceptAndReadTracks,
  getTrack3,
  cancelInsert,
} from "./func/modeFunc/idCardStep";
import { ReadBarcode, CancelReadBarcode } from "./func/modeFunc/bcrStep";
import { PrintRawData } from "./func/modeFunc/prrStep";
import {
  StartDisplay,
  StopDisplay,
  TakePicture,
} from "./func/modeFunc/takePictureStep";
import type {
  BaseOpt,
  CamData,
  DoubleCamData,
  DoubleCamDataOpt,
  GetHighCameraStreamParam,
  GetKeyType,
  PrinterQueneParam,
  PrintPrrParam,
  PrintColorParam,
  FingerOpt,
  SaveFingerDataOpt,
  BaseFingerDataOpt,
  NetworkInfo,
} from "./types";
// import type { Get} from "./types";
import { keyCodeMaps, StatusCode, statusCodeDescription } from "./code";
import type { KeyCodeMapKeys } from "./code";
import { useModule } from "./func/createMod";
import { base64ToHex, getCallBackParam } from "./func/utils";
import {
  CancelWaitAccept,
  ReadEigenvalue,
  ReadTemplate,
  VerifyFinger,
} from "./func/modeFunc/fingerStep";
import { debug } from "console";

let imageFileId = 0;

class SDKInterface {
  private isActiveGetData = false;
  constructor(opt: BaseOpt) {
    initDevice().then((device) => {
      debugger;
      opt.success(getCallBackParam(StatusCode.Success))
    }).catch((error) => {
      opt.fail(getCallBackParam(StatusCode.InitFail))
    })
  }
  getIDCard(opt: BaseOpt) {
    acceptAndReadTracks()
      .then((ret) => {
        if (ret === "CardAccepted") {
          getTrack3().then((ret) => {
            opt.success({
              code: StatusCode.Success,
              message: statusCodeDescription[StatusCode.Success],
              data: ret,
              ok: true,
            });
          });
        } else {
          opt.fail({
            code: StatusCode.CardReadFail,
            message: statusCodeDescription[StatusCode.CardReadFail],
            data: null,
            ok: false,
          });
        }
      })
      .catch((err) => {
        opt.fail({
          code: StatusCode.NoModules,
          message: statusCodeDescription[StatusCode.NoModules],
          data: null,
          ok: false,
        });
      });
  }

  closeIdCard(opt: BaseOpt) {
    cancelInsert()
      .then((ret) => {
        if (ret === "CardAcceptCancelled") {
          opt.success({
            code: StatusCode.Success,
            message: statusCodeDescription[StatusCode.Success],
            data: null,
            ok: true,
          });
        } else {
          opt.fail({
            code: StatusCode.CardCancelFail,
            message: statusCodeDescription[StatusCode.CardCancelFail],
            data: null,
            ok: false,
          });
        }
      })
      .catch((err) => {
        opt.fail({
          code: StatusCode.NoModules,
          message: statusCodeDescription[StatusCode.NoModules],
          data: null,
          ok: false,
        });
      });
  }

  /**
   * 启动二维码扫描
   */
  readBarcode(opt: BaseOpt) {
    ReadBarcode({}, -1)
      .then((ret) => {
        if (ret?.ret === "BarcodeRead") {
          opt.success({
            code: StatusCode.Success,
            message: statusCodeDescription[StatusCode.Success],
            data: ret.param[0],
            ok: true,
          });
        } else {
          opt.fail({
            code: StatusCode.ReadBarcodeFail,
            message: statusCodeDescription[StatusCode.ReadBarcodeFail],
            data: null,
            ok: false,
          });
        }
      })
      .catch((err) => {
        opt.fail({
          code: StatusCode.NoModules,
          message: statusCodeDescription[StatusCode.NoModules],
          data: null,
          ok: false,
        });
      });
  }

  /**
   * 关闭二维码扫描
   */
  closeBcr(opt: BaseOpt) {
    CancelReadBarcode({})
      .then((ret) => {
        if (ret === "ReadBarcodeCancelled") {
          opt.success({
            code: StatusCode.Success,
            message: statusCodeDescription[StatusCode.Success],
            data: null,
            ok: true,
          });
        } else {
          opt.fail({
            code: StatusCode.BarcodeCancelFail,
            message: statusCodeDescription[StatusCode.BarcodeCancelFail],
            data: null,
            ok: false,
          });
        }
      })
      .catch((err) => {
        opt.fail({
          code: StatusCode.NoModules,
          message: statusCodeDescription[StatusCode.NoModules],
          data: null,
          ok: false,
        });
      });
  }

  getHighCameraStream(opt: GetHighCameraStreamParam) {
    StartDisplay(
      {
        mod: "cam",
      },
      opt
    )
      .then((ret) => {
        if (ret === "DisplayStarted") {
          opt.success(getCallBackParam(StatusCode.Success));
        } else {
          opt.fail(getCallBackParam(StatusCode.hStartDisplayFail));
        }
      })
      .catch((err) => {
        opt.fail(getCallBackParam(StatusCode.NoModules));
      });
  }
  closeHighCamera(opt: BaseOpt) {
    StopDisplay({ mod: "cam" })
      .then((ret) => {
        if (ret === "DisplayStoped") {
          opt.success(getCallBackParam(StatusCode.Success));
        } else {
          opt.fail(getCallBackParam(StatusCode.hStopDisplayFail));
        }
      })
      .catch((err) => {
        opt.fail(getCallBackParam(StatusCode.NoModules));
      });
  }

  getHighCamera(opt: BaseOpt<CamData | null>) {
    let imageFileIdSave = imageFileId;
    const io = useModule();
    const { common } = io;
    if (!common) {
      opt.fail(getCallBackParam(StatusCode.NoModules));
      return;
    }
    TakePicture({ mod: "cam" }, imageFileId.toString()).then((ret) => {
      if (ret === "TakePictureSuccess") {
        let path = `c:\\camera\\CustomerImg${imageFileIdSave}.jpg`;
        common.ReadImageBase64(path).then((BASE64) => {
          opt.success(
            getCallBackParam(StatusCode.Success, {
              file: BASE64,
              filename: path,
            })
          );
        });
      } else {
        opt.fail(getCallBackParam(StatusCode.hTakePictureFail));
      }
    });
    imageFileId++;
  }

  getVideoCamera(opt: GetHighCameraStreamParam) {
    StartDisplay(
      {
        mod: "face",
      },
      opt
    )
      .then((ret) => {
        if (ret === "DisplayStarted") {
          opt.success(getCallBackParam(StatusCode.Success));
        } else {
          opt.fail(getCallBackParam(StatusCode.dStartDisplayFail));
        }
      })
      .catch((err) => {
        opt.fail(getCallBackParam(StatusCode.NoModules));
      });
  }

  closeVideoCamera(opt: BaseOpt) {
    StopDisplay({ mod: "face" }, true)
      .then((ret) => {
        if (ret === "DisplayStoped") {
          opt.success(getCallBackParam(StatusCode.Success));
        } else {
          opt.fail(getCallBackParam(StatusCode.dStopDisplayFail));
        }
      })
      .catch((err) => {
        opt.fail(getCallBackParam(StatusCode.NoModules));
      });
  }

  /**
   * 获取双目摄像头图片
   * @param opt - BaseOpt
   * @returns void
   */
  getDoubleCamera(opt: BaseOpt<DoubleCamData | null> & DoubleCamDataOpt) {
    let imageFileIdSave = imageFileId;
    const io = useModule();
    const { common } = io;
    if (!common) {
      opt.fail(getCallBackParam(StatusCode.NoModules));
      return;
    }
    let prm;
    let { mode = "checkLiving" } = opt;
    let living: GetKeyType<DoubleCamData, "living">;
    if (mode === "picture") {
      living = "none";
      prm = TakePicture({ mod: "face" }, imageFileId.toString(), true);
    } else {
      living = "true";
      prm = TakePicture({ mod: "face" }, imageFileId.toString());
    }
    prm.then((ret) => {
      if (ret === "TakePictureSuccess" || ret === "TakePictureEXSuccess") {
        let path = `c:\\camera\\CustomerImg${imageFileIdSave}-Vl.jpg`;
        let path2 = `c:\\camera\\CustomerImg${imageFileIdSave}-Ir.jpg`;
        let base64_1 = "";
        let base64_2 = "";
        common
          .ReadImageBase64(path)
          .then((BASE64) => {
            base64_1 = BASE64;
            return common.ReadImageBase64(path2);
          })
          .then((BASE64) => {
            base64_2 = BASE64;
            opt.success(
              getCallBackParam(StatusCode.Success, {
                fileVl: base64_1,
                filenameVl: path,
                fileIr: base64_2,
                filenameIr: path2,
                living,
              })
            );
          });
      } else {
        opt.fail(getCallBackParam(StatusCode.dTakePictureFail));
      }
    });
    imageFileId++;
  }
  printPrr(opt: PrintPrrParam) {
    PrintRawData({}, opt.strData).then((ret) => {
      if (ret === "PrintComplete") {
        opt.success({
          code: StatusCode.Success,
          message: statusCodeDescription[StatusCode.Success],
          data: null,
          ok: true,
        });
      } else {
        opt.fail({
          code: StatusCode.PrintRawDataFail,
          message: statusCodeDescription[StatusCode.PrintRawDataFail],
          data: null,
          ok: false,
        });
      }
    });
  }

  getPrinterList(opt: BaseOpt) {
    const io = useModule();
    const { common } = io;
    if (!common) {
      opt.fail(getCallBackParam(StatusCode.NoModules));
      return;
    }
    common.GetPrinterNames().then((ret) => {
      opt.success(getCallBackParam(StatusCode.Success, ret));
    });
  }

  getPrintQueue(opt: PrinterQueneParam) {
    console.log(opt.strPrinter);
    const io = useModule();
    const { common } = io;
    if (!common) {
      opt.fail(getCallBackParam(StatusCode.NoModules));
      return;
    }

    common.GetPrinterJobsByName(opt.strPrinter).then((ret) => {
      common.GetPrinterJobsByName(opt.strPrinter).then((ret) => {
        opt.success({
          code: StatusCode.Success,
          message: statusCodeDescription[StatusCode.Success],
          data: ret,
          ok: true,
        });
      });
    });
  }

  getNumLock(opt: BaseOpt<number>) {
    const io = useModule();
    const { pin } = io;
    if (!pin) {
      opt.fail(getCallBackParam(StatusCode.NoModules));
      return;
    }
    if (this.isActiveGetData) {
      return;
    }
    this.isActiveGetData = true;
    pin
      .UserEntry((param) => {
        if (param.ret === "KeyPressed") {
          let codeSetting = keyCodeMaps[param.param[0] as KeyCodeMapKeys];
          for (let index = 0; index < codeSetting.runCount; index++) {
            opt.success(
              getCallBackParam(StatusCode.Success, codeSetting.keyCode)
            );
          }
        }
      })
      .then((ret) => {
        if (ret) {
          if (ret.ret === "EntryComplete") {
            opt.success(getCallBackParam(StatusCode.Success));
          } else if (ret.ret === "Timeout") {
            opt.fail(getCallBackParam(StatusCode.Timeout));
          } else if (ret.ret === "DeviceError") {
            opt.fail(getCallBackParam(StatusCode.DeviceError));
          } else if (ret.ret === "FatalError") {
            opt.fail(getCallBackParam(StatusCode.FatalError));
          }
        } else {
          opt.fail(getCallBackParam(StatusCode.PinCancel));
        }
      });
  }

  closeNumLock(opt: BaseOpt) {
    const io = useModule();
    const { pin } = io;
    if (!pin) {
      opt.fail(getCallBackParam(StatusCode.NoModules));
      return;
    }
    if (!this.isActiveGetData) {
      opt.fail(getCallBackParam(StatusCode.PinGetDataNoActive));
      return;
    }
    pin.CancelUserEntry().then((ret) => {
      this.isActiveGetData = false;
      opt.success(getCallBackParam(StatusCode.Success));
    });
  }

  printer(opt: PrintColorParam) {
    const io = useModule();
    const { common } = io;
    if (!common) {
      opt.fail(getCallBackParam(StatusCode.NoModules));
      return;
    }
    let hexPdf = base64ToHex(opt.fileData);
    const filePath = "c:\\printPdf.pdf";
    common.WriteFile(filePath, hexPdf, "Binary", "").then((ret) => {
      console.log(ret);
      common
        .PrintPdf(filePath, opt.printerName, Number(opt.pageFormat))
        .then((ret2) => {
          if (ret == 0) {
            console.log("成功");
            opt.success(getCallBackParam(StatusCode.Success, ret2));
          } else {
            console.log("失败1");
            opt.fail(getCallBackParam(StatusCode.PrinterFail, null));
          }
        });
    });
    console.log("写文件c盘");
  }

  saveFingerTemplate(opt: BaseOpt<SaveFingerDataOpt> & FingerOpt) {
    let path = `${opt.fingerId}.txt`;
    let data: SaveFingerDataOpt = {
      fingerId: opt.fingerId,
      readCount: 1,
      status: StatusCode.FingerDetected,
      statusMsg: statusCodeDescription[StatusCode.FingerDetected],
    };
    ReadTemplate(0, path, (ret) => {
      if (ret === "FingerDetected") {
        (data.status = StatusCode.FingerDetected),
          (data.statusMsg = statusCodeDescription[StatusCode.FingerDetected]),
          opt.success(getCallBackParam(StatusCode.Success, data));
      } else if (ret === "FingerTaken") {
        (data.status = StatusCode.FingerTaken),
          (data.statusMsg = statusCodeDescription[StatusCode.FingerTaken]),
          opt.success(getCallBackParam(StatusCode.Success, data));
        data.readCount++;
      }
    })
      .then((ret) => {
        switch (ret) {
          case "ReadSuccessful":
            (data.status = StatusCode.FingerSaveSuccessful),
              (data.statusMsg =
                statusCodeDescription[StatusCode.FingerSaveSuccessful]),
              opt.success(getCallBackParam(StatusCode.Success, data));
            break;
          case "DeviceError":
            opt.fail(getCallBackParam(StatusCode.DeviceError));
            break;
          default:
            opt.fail(getCallBackParam(StatusCode.FatalError));
        }
      })
      .catch((err) => {
        opt.fail(getCallBackParam(StatusCode.NoModules));
      });
  }
  deleteFingerTemplate(opt: BaseOpt<{ fingerId: string }> & FingerOpt) {
    const { common } = useModule();
    if (!common) throw new Error(`没有fpc模块`);
    common
      .IsFileExist(`c:\\finger\\template\\${opt.fingerId}.txt`)
      .then((ret) => {
        if (ret === 1) {
          common
            .DeleteFile(`c:\\finger\\template\\${opt.fingerId}.txt`)
            .then((ret) => {
              if (ret === 0) {
                opt.success(
                  getCallBackParam(StatusCode.Success, {
                    fingerId: opt.fingerId,
                  })
                );
              } else {
                opt.fail(getCallBackParam(StatusCode.FingerTemplateDeleteFail));
              }
            });
        } else {
          opt.fail(getCallBackParam(StatusCode.FingerTemplateNoExist));
        }
      });
  }
  readFinger(opt: BaseOpt<BaseFingerDataOpt>) {
    let data: BaseFingerDataOpt = {
      status: StatusCode.FingerDetected,
      statusMsg: statusCodeDescription[StatusCode.FingerDetected],
    };
    ReadEigenvalue(0, "c:\\finger\\currentFinger.txt", (ret) => {
      if (ret === "FingerDetected") {
        (data.status = StatusCode.FingerDetected),
          (data.statusMsg = statusCodeDescription[StatusCode.FingerDetected]),
          opt.success(getCallBackParam(StatusCode.Success, data));
      } else if (ret === "FingerTaken") {
        (data.status = StatusCode.FingerTaken),
          (data.statusMsg = statusCodeDescription[StatusCode.FingerTaken]),
          opt.success(getCallBackParam(StatusCode.Success, data));
      }
    })
      .then((ret) => {
        switch (ret) {
          case "ReadSuccessful":
            (data.status = StatusCode.FingerReadSuccessful),
              (data.statusMsg =
                statusCodeDescription[StatusCode.FingerReadSuccessful]),
              opt.success(getCallBackParam(StatusCode.Success, data));
            break;
          case "DeviceError":
            opt.fail(getCallBackParam(StatusCode.DeviceError));
            break;
          default:
            opt.fail(getCallBackParam(StatusCode.FatalError));
        }
      })
      .catch((err) => {
        opt.fail(getCallBackParam(StatusCode.NoModules));
      });
  }
  verifyFinger(opt: BaseOpt) {
    VerifyFinger()
      .then((ret) => {
        switch (ret) {
          case "ReadSuccessful":
            opt.success(getCallBackParam(StatusCode.Success));
            break;
          case "DataMissing":
            opt.fail(getCallBackParam(StatusCode.FingerTemplateNoExist));
            break;
          case "DataNotSupport":
            opt.fail(getCallBackParam(StatusCode.FingerDataNotSupport));
            break;
          case "DeviceError":
            opt.fail(getCallBackParam(StatusCode.DeviceError));
            break;
          default:
            opt.fail(getCallBackParam(StatusCode.FatalError));
        }
      })
      .catch((err) => {
        opt.fail(getCallBackParam(StatusCode.NoModules));
      });
  }
  closeFinger(opt: BaseOpt) {
    CancelWaitAccept()
      .then((ret) => {
        switch (ret) {
          case "WaitCanceled":
            opt.success(getCallBackParam(StatusCode.Success));
            break;
          case "DeviceError":
            opt.fail(getCallBackParam(StatusCode.DeviceError));
            break;
          default:
            opt.fail(getCallBackParam(StatusCode.FatalError));
        }
      })
      .catch((err) => {
        opt.fail(getCallBackParam(StatusCode.NoModules));
      });
  }

  getNetworkAddr(opt: BaseOpt<NetworkInfo[]>) {
    const io = useModule();
    const { common } = io;
    if (!common) {
      opt.fail(getCallBackParam(StatusCode.NoModules));
      return;
    }
    common.GetNetworkInfo().then((ret) => {
      let networkInfo: NetworkInfo[] = [];
      for (const macInfo of ret.MACINFO) {
        for (const ipAddress of macInfo.IPARRAY) {
          let info:NetworkInfo = {
            mac: macInfo.MACADDRESS,
            ipv4: ipAddress.IP,
          }
          networkInfo.push(info)
        }
      }
      opt.success(getCallBackParam(StatusCode.Success, networkInfo));
    })
  }
}

export interface JsInterface {
  SDKInterface: new (opt: BaseOpt) => SDKInterface;
  getDeviceJsSDK: Function;
}

const jsInterface: JsInterface = {
  SDKInterface: SDKInterface,
  getDeviceJsSDK: function () {},
};

export default jsInterface;
